package site.yunnong.atvris.service.impl;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import site.yunnong.atvris.common.api.Page;
import site.yunnong.atvris.common.dto.SearchUserParam;
import site.yunnong.atvris.common.dto.UserQueryParam;
import site.yunnong.atvris.common.enumeration.UserStatusEnum;
import site.yunnong.atvris.dao.domain.ext.UserDetail;
import site.yunnong.atvris.dao.mapper.UserMapper;
import site.yunnong.atvris.dao.mapper.ext.UserExtMapper;
import site.yunnong.atvris.service.EsUserService;
import site.yunnong.atvris.service.InteractionService;
import site.yunnong.atvris.service.domain.EsUser;
import site.yunnong.atvris.service.helper.OperatorHelper;
import site.yunnong.atvris.service.repository.EsUserRepository;
import site.yunnong.atvris.service.vo.UserCardVO;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author zjh
 * @date 2021/9/30 23:19
 */
@Slf4j
@Service
public class EsUserServiceImpl implements EsUserService {

    @Resource
    private UserMapper userMapper;
    @Resource
    private UserExtMapper userExtMapper;
    @Resource
    private EsUserRepository esUserRepository;
    @Resource
    private InteractionService interactionService;
    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    
    @Override
    public int importAll() {
        UserQueryParam param = new UserQueryParam();
        param.setStatus(UserStatusEnum.ACTIVE.getValue());
        List<UserDetail> queryUserList = userExtMapper.queryUserList(param);

        // UserDetail转EsUser
        List<EsUser> esUserList = Optional.of(queryUserList).orElse(Lists.newArrayList()).stream().map(this::buildEsUser).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(esUserList)) {
            try {
                Iterable<EsUser> iterable = esUserRepository.saveAll(esUserList);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
            int result = 0;
//            for (EsUser esUser : iterable) {
//                result++;
//            }
//            return result;
            return esUserList.size();
        }
        return 0;
    }

    private EsUser buildEsUser(UserDetail userDetail) {
        EsUser esUser = new EsUser();
        BeanUtils.copyProperties(userDetail, esUser);
        esUser.setId(userDetail.getUuid());
        return esUser;
    }

    @Override
    public void delete(Long id) {
        esUserRepository.deleteById(id);
    }

    @Override
    public void create(Long id) {
        // 搜单个
        UserQueryParam param = new UserQueryParam();
        param.setUuid(id);
        param.setStatus(UserStatusEnum.ACTIVE.getValue());
        List<UserDetail> queryUserList = userExtMapper.queryUserList(param);
        if (CollectionUtils.isNotEmpty(queryUserList)) {
            EsUser esUser = buildEsUser(queryUserList.get(0));
            esUserRepository.save(esUser);
        }
    }

    @Override
    public void delete(List<Long> ids) {
        if (CollectionUtils.isNotEmpty(ids)) {
            List<EsUser> esUserList = Lists.newArrayList();
            for (Long id: ids) {
                EsUser esUser = new EsUser();
                esUser.setId(id);
                esUserList.add(esUser);
            }
            esUserRepository.deleteAll(esUserList);
        }
        esUserRepository.deleteAll();
    }

    @Override
    public Page<UserCardVO> search(SearchUserParam param) {
        // 分页， jpa page从0开始
        Pageable pageable = PageRequest.of(param.getPageNum() - 1, param.getPageSize());
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withPageable(pageable);
        // 模糊查询
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        // 一种中文检索 一种like检索
        boolQueryBuilder.should(QueryBuilders.queryStringQuery(param.getNickname()).field("nickname"))
                .should(QueryBuilders.wildcardQuery("nickname", ("*" + param.getNickname() + "*").toLowerCase()));
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        NativeSearchQuery searchQuery = nativeSearchQueryBuilder.build();
        log.info("DSL:{}", searchQuery.getQuery().toString());
        SearchHits<EsUser> searchHits = elasticsearchRestTemplate.search(searchQuery, EsUser.class);
        if (searchHits.getTotalHits() <= 0) {
            return new Page<>(param.getPageNum(), param.getPageSize(), 0L, Lists.newArrayList());
        }
        List<EsUser> esVideoList = searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList());
        Long loginUuid = OperatorHelper.isLogin() ? OperatorHelper.getLoginUuid() : null;
        List<UserCardVO> userCardVOList = Optional.of(esVideoList).orElse(Lists.newArrayList()).stream().map(item ->buildUserCardVO(loginUuid, item)).collect(Collectors.toList());
        return new Page<>(param.getPageNum(), param.getPageSize(), searchHits.getTotalHits(), userCardVOList);
    }

    private UserCardVO buildUserCardVO(Long loginUuid, EsUser esUser) {
        UserCardVO vo = new UserCardVO();
        BeanUtils.copyProperties(esUser, vo);
        vo.setUuid(esUser.getId());
        vo.setFansCount((int)interactionService.findUserFansCount(esUser.getId()));
        vo.setHasFollowed(interactionService.hasFollowed(loginUuid, esUser.getId()));
        return vo;
    }
}
